/*
 *  The stupid codes try to use openGL on android
 */
import java.io.InputStream;
import java.util.Random;
import java.nio.FloatBuffer;
import java.nio.ByteBuffer;

import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.view.WindowManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;

public class GLActivity extends Activity{

	private GLSurfaceView mGLSurfaceView;

	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		// set full screen
		requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

		mGLSurfaceView = new GLSurfaceView(this);
		mGLSurfaceView.setRenderer(new GLES20Renderer(this));

        setContentView(mGLSurfaceView);
	}

	@Override
	public void onResume(){
		super.onResume();
		mGLSurfaceView.onResume();
	}

	@Override
	public void onPause(){
		super.onPause();
		mGLSurfaceView.onPause();
	}

	class GLES20Renderer implements GLSurfaceView.Renderer{

		private Context mContext;

		private final int PARTICLE_COUNT = 500;
		private int mTextureId;

		private float slowdown = 4.0f;
		private float xspeed = 0.0f;
		private float yspeed = -0.4f;
		private float zoom = -20.0f;

		private particle[] particles = new particle[PARTICLE_COUNT];

		private float[] texCoord = {
			1.0f,1.0f,
			0.0f,1.0f,
			1.0f,0.0f,
			0.0f,0.0f
		};

		private byte[] drawIndices = {
			0,1,2,3
		};

		private final float[][] colors = {
			{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
			{0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
			{0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}
		};

		class particle{
			float life;
			float fade;
			float r;
			float g;
			float b;
			float x;
			float y;
			float z;
			float xi;
			float yi;
			float zi;
		}

		public GLES20Renderer(Context context){
			mContext = context;
		}

		private void setParticles(){
			for(int i = 0;i < PARTICLE_COUNT;i++){
				particle p = new particle();
				p.life = 1.0f;																// give all the particles full life
				p.fade = (float)((new Random()).nextLong() % 100) / 1000.0f + 0.003f;		// random fade speed
				p.r = colors[i % 12][0];													// select rainbow color
				p.g = colors[i % 12][1];
				p.b = colors[i % 12][2];
				p.x = 0.0f;
				p.y = 0.0f;
				p.z = 0.0f;
				p.xi = ((float)((new Random()).nextLong() % 50) - 26.0f) * 10.0f;			// random speed on x,y,z axis
				p.yi = ((float)((new Random()).nextLong() % 50) - 25.0f) * 10.0f;
				p.zi = ((float)((new Random()).nextLong() % 50) - 25.0f) * 10.0f;
				particles[i] = p;
			}
		}

		@Override
		public void onSurfaceCreated(GL10 gl,EGLConfig config){

			InputStream is = mContext.getResources().openRawResource(R.raw.particle);
			Bitmap bitmap;
			try{
				bitmap = BitmapFactory.decodeStream(is);
			} finally{
				try{
					is.close();
				} catch(Exception e){
					// ignore
				}
			}

			int[] textures = new int[1];
			GLES20.glGenTextures(1,textures,0);
			mTextureId = textures[0];
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,mTextureId);
			GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
			GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
			GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,bitmap,0);

			bitmap.recycle();

			gl.glShadeModel(GL10.GL_SMOOTH);
			GLES20.glClearColor(0.0f,0.0f,0.0f,0.0f);
			GLES20.glClearDepthf(1.0f);
			GLES20.glDisable(GLES20.GL_DEPTH_TEST);
			GLES20.glEnable(GLES20.GL_BLEND);
			GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE);
			GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GLES20.GL_NICEST);
			GLES20.glHint(GL10.GL_POINT_SMOOTH_HINT,GLES20.GL_NICEST);
			GLES20.glEnable(GLES20.GL_TEXTURE_2D);

			setParticles();
		}

		@Override
		public void onSurfaceChanged(GL10 gl,int width,int height){
			GLES20.glViewport(0,0,width,height);

			gl.glMatrixMode(GL10.GL_PROJECTION);
			gl.glLoadIdentity();

			GLU.gluPerspective(gl,45.0f,(float)width / (float)height,0.1f,100.0f);

			gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();
		}

		@Override
		public void onDrawFrame(GL10 gl){
			GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
			gl.glLoadIdentity();

			for(int i = 0;i < PARTICLE_COUNT;i++){
				particle p = particles[i];
				float x = p.x;
				float y = p.y;
				float z = p.z + zoom;

				gl.glColor4f(p.r,p.g,p.b,p.life);

				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

				FloatBuffer texCoordBuf = FloatBuffer.allocate(texCoord.length);
				texCoordBuf.put(texCoord);
				texCoordBuf.position(0);
				gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,texCoordBuf);

				float[] vertexes = {
					x + 0.5f,y + 0.5f,z,
					x - 0.5f,y + 0.5f,z,
					x + 0.5f,y - 0.5f,z,
					x - 0.5f,y - 0.5f,z,
				};
				FloatBuffer vertexBuf = FloatBuffer.allocate(vertexes.length);
				vertexBuf.put(vertexes);
				vertexBuf.position(0);
				gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuf);

				ByteBuffer indicesBuf = ByteBuffer.allocate(drawIndices.length);
				indicesBuf.put(drawIndices);
				indicesBuf.position(0);

				gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,drawIndices.length,GL10.GL_UNSIGNED_BYTE,indicesBuf);

				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

				p.x += p.xi / (slowdown * 1000);
				p.y += p.yi / (slowdown * 1000);
				p.z += p.zi / (slowdown * 1000);

				p.xi += xspeed;
				p.yi += yspeed;

				p.life -= p.fade;

				if(p.life < 0.0f){
					p.life = 1.0f;
					p.fade = (float)((new Random()).nextLong() % 100) / 1000.0f + 0.03f;
					p.x = 0.0f;
					p.y = 0.0f;
					p.z = 0.0f;
					p.xi = xspeed + (float)((new Random()).nextLong() % 60) - 32.0f;
					p.yi = yspeed + (float)((new Random()).nextLong() % 60) - 32.0f;
					p.zi = (float)((new Random()).nextLong() % 60) - 30.0f;
				}
			}

			GLES20.glFlush();
		}
	}
}
